using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using star_questionnair.Models;
using star_questionnair.Models.Enum;
using star_questionnair.Services;
using star_questionnair.Services.impl;
using star_questionnair.Utilities;

namespace star_questionnair.Services.impl;

public class CrossAnalysisService
{
        private readonly IQuestionService _questionService;
        private readonly IOptionService _optionService;
        private readonly IAnswerService _answerService;
        private readonly IResponseService _responseService;
        private readonly IHistoryService _historyService;
        private readonly ILogger<CrossAnalysisService> _logger;

        public CrossAnalysisService(
            IQuestionService questionService,
            IOptionService optionService,
            IAnswerService answerService,
            IResponseService responseService,
            IHistoryService historyService,
            ILogger<CrossAnalysisService> logger)
        {
            _questionService = questionService;
            _optionService = optionService;
            _answerService = answerService;
            _responseService = responseService;
            _historyService = historyService;
            _logger = logger;
        }

        public async Task<Dictionary<string, Dictionary<string, double>>> CrossAnalyzeAsync(int xQuestionId, int yQuestionId)
        {
            // 获取问题
            var xQuestion = await _questionService.GetQuestionByIdAsync(xQuestionId);
            var yQuestion = await _questionService.GetQuestionByIdAsync(yQuestionId);

            // 验证是否属于同一问卷
            if (xQuestion.QuestionnaireId != yQuestion.QuestionnaireId)
            {
                throw new ArgumentException("Questions must belong to the same questionnaire.");
            }

            // 验证问题类型
            if (QuestionEnumExtensions.IsTextType(xQuestion.Type) || QuestionEnumExtensions.IsSortType(xQuestion.Type) ||
                QuestionEnumExtensions.IsTextType(yQuestion.Type) || QuestionEnumExtensions.IsSortType(yQuestion.Type))
            {
                throw new ArgumentException("Text and Sort type questions are not allowed.");
            }

            // 获取X变量的取值
            var xValues = await GetQuestionValuesAsync(xQuestion);
            // 获取Y变量的取值
            var yValues = await GetQuestionValuesAsync(yQuestion);

            // 获取响应
            var responses =  _historyService.GetListResponsesByQuestionnaireId(xQuestion.QuestionnaireId);

            // 构建结果数据结构
            var result = new Dictionary<string, Dictionary<string, double>>();

            // 遍历X变量的每个取值
            foreach (var xValue in xValues)
            {
                var yDistribution = yValues.ToDictionary(yValue => yValue, yValue => 0.0);
                result[xValue] = yDistribution;
            }

            // 遍历所有响应
            foreach (var response in responses)
            {
                // 获取该响应下的所有答案
                var answers =  _historyService.GetAnswersByResponseId(response.Id);

                // 过滤出对应X变量和Y变量的答案
                var xAnswer = answers.FirstOrDefault(a => a.QuestionId == xQuestionId);
                var yAnswer = answers.FirstOrDefault(a => a.QuestionId == yQuestionId);

                // 如果存在有效的答案，进行统计
                if (xAnswer != null && yAnswer != null)
                {
                    var xValue = await GetAnswerValueAsync(xAnswer, xQuestion.Type);
                    var yValue = await GetAnswerValueAsync(yAnswer, yQuestion.Type);
                    if (result.ContainsKey(xValue) && result[xValue].ContainsKey(yValue))
                    {
                        result[xValue][yValue]++;
                    }
                }
            }

            // 计算百分比
            foreach (var xValue in result.Keys.ToList())
            {
                var yDistribution = result[xValue];
                var total = yDistribution.Values.Sum();
                if (total > 0)
                {
                    foreach (var yValue in yDistribution.Keys.ToList())
                    {
                        yDistribution[yValue] = yDistribution[yValue] / total;
                    }
                }
            }

            return result;
        }

        private async Task<List<string>> GetQuestionValuesAsync(Question question)
        {
            if (QuestionEnumExtensions.IsChoiceType(question.Type))
            {
                var options =  _historyService.GetOptionsByQuestionId(question.Id);
                return options.Select(option => option.Content).ToList();
            }
            else if (QuestionEnumExtensions.IsLevelType(question.Type))
            {
                return new List<string> { "1", "2", "3", "4", "5" };
            }
            return new List<string>();
        }

        private async Task<string> GetAnswerValueAsync(Answer answer, string questionType)
        {
            if (QuestionEnumExtensions.IsChoiceType(questionType))
            {
                var option =  _optionService.GetById(int.Parse(answer.Content));
                return option.Content;
            }
            else if (QuestionEnumExtensions.IsLevelType(questionType))
            {
                return answer.Text;
            }
            return string.Empty;
        }
}